<template>
	<div class="mainWindow">
		<div class="setName" v-if="setName">
			<div class="dialog">
				<label>请输入用户名</label>
				<input type="text" v-model="userName" />
				<button @click="handleSetName">提交</button>
			</div>
		</div>
		<div class="appWindow">
			<!-- 左边显示视频 -->
			<div class="leftVideoView">
				<div class="upLoadVideo video" v-show="ifVideo">
					<input type="file" @change="handleVideoUpload" v-if="uploadVideo" />
					<div class="video" v-else>
						<div class="tips" v-if="!hasResult">等待视频加载...</div>
						<div class="calPic" v-else>
							<img :src="'data:image/png;base64,' + picBase64" />
						</div>
					</div>
				</div>
				<div class="openCamera video" v-show="!ifVideo">
					<div class="calPic">
						<img :src="'data:image/png;base64,' + picBase64" />
					</div>
				</div>
			</div>
			<!-- 右边显示选择 -->
			<div class="rightSelection">
				<div class="hello">
					<p>你好，{{ userName }}</p>
				</div>
				<div class="chooseVideo">
					<p>选择跳绳计算方法</p>
					<div class="choice">
						<button @click="handleUploadVideo">上传视频</button>
						<button @click="handleOpenCamera">打开摄像头</button>
					</div>
				</div>
				<div class="count">
					<p>跳绳次数：</p>
					<p id="count">{{ count }}</p>
					<!-- 曲线图 -->
					<div class="chart">
						<div ref="chartRef" style="width: 100%; height: 250px"></div>
					</div>
				</div>
				<div class="camerapanel panel" v-if="!ifVideo">
					<div class="startCount">
						<button @click="startCount" v-if="!startC">开始计数</button>
						<button @click="endCount" v-else>结束计数</button>
					</div>
					<div class="1minCount">
						<button @click="oneMinCount">1分钟计数</button>
					</div>
				</div>
				<div class="videopanel panel" v-if="ifVideo">
					<div class="stopVideo">
						<button @click="pauseVideo">停止视频</button>
					</div>
				</div>
			</div>
		</div>
	</div>
</template>

<script setup lang="ts">
		import { ref, onBeforeUnmount, watch, onMounted, onUnmounted } from "vue";
		import axios from "axios";
		import io from "socket.io-client";
		import * as echarts from "echarts";

		const setName = ref(true);
		const userName = ref("");
		const ifVideo = ref(true); // true: 上传视频，false: 打开摄像头
		const videoSrc = ref(""); // 视频地址
		const uploadVideo = ref(true); // true: 上传视频，false: 视频加载完成
		let cameraStream: MediaStream | null = null;

		const hasResult = ref(false);
		const defalutpic =
			"/9j/4AAQSkZJRgABAQEAAAAAAAD/4QAuRXhpZgAATU0AKgAAAAgAAkAAAAMAAAABAG0AAEABAAEAAAABAAAAAAAAAAD/2wBDAAoHBwkHBgoJCAkLCwoMDxkQDw4ODx4WFxIZJCAmJSMgIyIoLTkwKCo2KyIjMkQyNjs9QEBAJjBGS0U+Sjk/QD3/2wBDAQsLCw8NDx0QEB09KSMpPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT3/wAARCAEKAdoDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDyaiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACikpaACj19utS29ncXW77PC8m0ZO0ZxXS6B4Ph1fR3uprho5ckKoH3cetAHKZA60vOCcHA6kDpXd+HH8NReGJ49Q8g3Kl1lLj5ye22p/CviXw5p3hKazvkQTYcMjR7jLnpz7cUAeeZHqKWvS/B9x4QTwdcDU1thcneZFlGZPbb9OKi8P/DGz1vwdJrB1B45mV3iAxtQL2PuaAPOaKt/2RqA083xsp/seceeEO0//AFqqUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABVzStOOp3Ji8zYqjJbGapoAXUMcAnB9q27yODTraOexk8ubOAQfvCgC/Y6mnhWaaznQyhjvVk4J+tYMmq3RkuGhmeGKdizRoeOarTTS3Ehkmcu7dSaZQAmB6UUtFACcVch1bULeyksre9nitZB80KuQpqpRQB6Xb/ABIgvfB0PhyPTyL2WNbUMSBGM8bvrWX4y+GsvhHRob8Xy3ClhHKpXbtY+nqK4kFg4ZWKspyGBxivQvBV5/wnOsCy8Wai1xb20W6CCR9gZvf1IFAHndLXQ+O9M0zRvFdxaaRKGtlAOA24Ix6jPfFc9QAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUA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";
		const picBase64 = ref(defalutpic);
		const count = ref(0);
		let socket: any = null;

		const startC = ref(false); // 开始计数

		const taskName = ref(""); // 任务名称

		const yChange = ref<number[]>([]); // y轴变化

	    let startTime = 0; // 开始时间


		// 设置用户名
		const handleSetName = () => {
			if (userName.value.trim()) {
				setName.value = false;
			} else {
				alert("请输入用户名");
			}
		};

		// 上传视频
		const handleVideoUpload = (e: Event) => {
			hasResult.value = false;
			const file = (e.target as HTMLInputElement).files?.[0];
			if (!file) return;

			const reader = new FileReader();
			reader.onload = () => {
				videoSrc.value = reader.result as string;
				uploadVideo.value = false;
			};
			reader.onerror = () => {
				alert("视频加载失败，请重试！");
			};
			reader.readAsDataURL(file);
			// 上传视频到服务器
			const formData = new FormData();
			formData.append("file", file);
			axios
				.post("http://localhost:7921/api/uploadVideo", formData, {
					headers: {
						"Content-Type": "multipart/form-data",
					},
				})
				.then((res) => {
					console.log(res.data);
					hasResult.value = true;
					// 建立websocket连接 实时传回计算后的图像
					socket = io("http://localhost:7921/calPic", {
						transports: ["websocket"],
						autoConnect: true,
						reconnection: true,
						reconnectionAttempts: 3,
						reconnectionDelay: 1000,
					});

					socket.on("connect", () => {
						console.log("connect");
					});

					socket.emit("calPic", res.data.file_path);

					socket.on("image_data", (data: any) => {
						picBase64.value = data.image;
	                    count.value = data.count;
	                    if (data.cy > 0) {
	                        yChange.value.push(data.cy);
	                    }

						if (yChange.value.length > 50) {

							yChange.value.shift(); // 移除最早的值
						}
					});

					socket.on("disconnect", () => {
						console.log("disconnect");
						socket = null;
					});

					socket.on("finish", () => {
						console.log("finish");
						socket.disconnect();
                        socket = null;
                        alert(`跳绳次数：${count.value}`);
					});

					socket.on("taskName", (data: any) => {
						// console.log(data.taskName);
						taskName.value = data.taskName;
					});
				})
				.catch((err) => {
					console.error(err);
				});
		};

		// 切换到上传视频模式
		const handleUploadVideo = () => {
			if (socket != null) {
				console.log("disconnect");
				socket.emit("stop", taskName.value);
				picBase64.value = defalutpic;
			}
			yChange.value = [];

			ifVideo.value = true;
			uploadVideo.value = true;
			count.value = 0;
		};

		// 打开摄像头
		const handleOpenCamera = async () => {
	        ifVideo.value = false;
	        count.value = 0;
			yChange.value = [];
			if (socket != null) {
				console.log("disconnect");

				socket.emit("stop", taskName.value);
				picBase64.value = defalutpic;
			}

			startC.value = false;

			axios
				.get("/api/starCamera")
				.then((res) => {
					console.log(res.data.task_name);
					taskName.value = res.data.task_name;
					hasResult.value = true;
					// 建立websocket连接 实时传回计算后的图像
					socket = io("http://localhost:7921/calPic", {
						transports: ["websocket"],
						autoConnect: true,
						reconnection: true,
						reconnectionAttempts: 3,
						reconnectionDelay: 1000,
					});

					socket.on("connect", () => {
						console.log("connect");
					});

                    socket.on("image_data", (data: any) => {
                        picBase64.value = data.image;
                        count.value = data.count;
                        if (startC.value && data.cy > 0) {
                            {

                                yChange.value.push(data.cy);

                            }
                            if (yChange.value.length > 50) {
                                yChange.value.shift(); // 移除最早的值
                            }
                        }
                    });

					socket.on("disconnect", () => {
						console.log("disconnect");
						socket = null;
					});

					socket.on("finish", () => {
						console.log("finish");
						socket.disconnect();
						socket = null;
					});

					socket.emit("startCamera", res.data.task_name);
				})
				.catch((err) => {
					console.error(err);
				});
		};

		// 开始计数
		const startCount = () => {
	        socket.emit("startCount", taskName.value);
	        startC.value = true;
	        count.value = 0;
	        yChange.value = [];
	        startTime = new Date().getTime();
	};

	    // 结束计数
	    const endCount = () => {
	        socket.emit("endCount", taskName.value);
	        startC.value = false;
	        const endTime = new Date().getTime();
	        const time = (endTime - startTime) / 1000;
	        alert(`跳绳次数：${count.value}，用时：${time}秒`);
	};

	    // 1分钟计数
	    const oneMinCount = () => {
	        socket.emit("startCount", taskName.value);
	        startC.value = true;
	        count.value = 0;
	        yChange.value = [];
	        setTimeout(() => {
	            socket.emit("endCount", taskName.value);
	            startC.value = false;
	            alert(`跳绳次数：${count.value}`);
	        }, 60000);

	    };

		// 停止计时
		const pauseVideo = () => {
			if (socket != null) {
				console.log("disconnect");
				socket.emit("stop", taskName.value);
			}
		};

		// 图表
		const chartRef = ref<HTMLElement | null>(null);
		let chartInstance: echarts.ECharts | null = null;
		// 初始化图表
		const initChart = () => {
			if (chartRef.value) {
				chartInstance = echarts.init(chartRef.value);
				const option: echarts.EChartsOption = {
					title: {
						text: "频率图",
					},
					tooltip: {
						trigger: "axis",
					},
					xAxis: {
						type: "category",
						data: [],
					},
					yAxis: {
						type: "value",
						min: 0,
					},
					series: [
						{
							name: "Y轴变化",
							type: "line",
							data: [],
						},
					],
				};
				chartInstance.setOption(option);
			}
		};

		// 计算Y轴的最小值
		const getMinYValue = (data: number[]): number => {
			return Math.min(...data);
		};

		// 更新图表数据
		const updateChart = () => {
			if (chartInstance && yChange.value.length > 0) {
				const xAxisData = yChange.value.map((_, index) => index.toString());
				const seriesData = yChange.value;
				const minYValue = getMinYValue(seriesData);
				chartInstance.setOption({
					xAxis: {
						data: xAxisData,
					},
					yAxis: {
						min: minYValue, // 设置Y轴最小值
					},
					series: [
						{
							data: seriesData,
						},
					],
				});
			}
		};

		// 监听yChange的变化并更新图表
		watch(
			yChange,
			() => {
				updateChart();
			},
			{ deep: true }
		);

		// 生命周期钩子
		onMounted(() => {
			initChart();
			updateChart();
		});

		onUnmounted(() => {
			if (chartInstance) {
				chartInstance.dispose();
				chartInstance = null;
	        }
	        if (socket != null) {
	            socket.disconnect();
	        }
		});

		// 组件卸载时清理资源
		onBeforeUnmount(() => {});
</script>

<style scoped>
	.hidden {
		display: none;
	}

	.mainWindow {
		position: fixed;
		bottom: 0px;
		top: 0px;
		left: 0px;
		right: 0px;
		background-color: antiquewhite;
	}

	.appWindow {
		width: 80%;
		height: 80%;
		background-color: white;
		position: absolute;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
		border-radius: 10px;
	}

	.setName {
		position: fixed;
		bottom: 0px;
		top: 0px;
		left: 0px;
		right: 0px;
		background-color: rgba(0, 0, 0, 0.5);
		display: flex;
		justify-content: center;
		align-items: center;
		z-index: 100;
	}

	.dialog {
		width: 300px;
		height: 200px;
		background-color: white;
		display: flex;
		flex-direction: column;
		justify-content: center;
		align-items: center;
		border-radius: 10px;
	}

	.dialog input {
		width: 200px;
		height: 30px;
		margin-bottom: 20px;
	}

	.hello {
		display: flex;
		justify-content: center;
		align-items: center;
		font-size: 20px;
		font-weight: bold;
	}

	.leftVideoView {
		width: 70%;
		height: 100%;
		background-color: lightblue;
		float: left;
		border-top-left-radius: 10px;
		border-bottom-left-radius: 10px;
	}

	.rightSelection {
		width: 30%;
		height: 100%;
		background-color: lightgreen;
		float: right;
		border-top-right-radius: 10px;
		border-bottom-right-radius: 10px;
	}

	.video {
		width: 90%;
		height: 90%;
		display: flex;
		justify-content: center;
		align-items: center;
		margin: auto;
		border-radius: 10px;
		margin-top: 5%;
		margin-bottom: 5%;
		background-color: lightblue;
	}

	.chooseVideo {
		margin-top: 10px;
	}

	.choice {
		display: flex;
		justify-content: center;
	}

	.chooseVideo p {
		font-size: 24px;
		font-weight: bold;
		margin: 10px;
		/* 居中 */
		display: flex;
		justify-content: center;
	}

	.choice button {
		background-color: #4caf50;
		color: white;
		border: none;
		border-radius: 5px;
		cursor: pointer;
		transition: background-color 0.3s, box-shadow 0.3s;
		margin: 5px;
		padding: 5px;
	}

	.chooseVideo button:hover {
		background-color: #45a049;
		box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.3);
	}

	#videoCamera {
		width: 100%;
		border-radius: 10px;
	}

	.calPic {
		width: 100%;
		height: 100%;
		border-radius: 10px;
		background-color: lightblue;
		display: flex;
		justify-content: center;
		align-items: center;
		overflow: hidden; /* 防止图片超出容器 */
		z-index: 100;
	}

	.calPic img {
		width: 100%;
		height: 100%;
		border-radius: 10px;
		object-fit: contain; /* 保持图片的宽高比，并使其在容器内居中 */
	}

	.count {
		margin-top: 10px;
		margin-left: 5px;
	}

	.count p {
		font-size: 24px;
		font-weight: bold;
		/* animation: countAnimation 1s infinite; */
	}

	#count {
		font-size: 48px;
		font-weight: bold;
		animation: countAnimation 1s infinite;
		/* 居中 */
		display: flex;
		justify-content: center;
	}

	@keyframes countAnimation {
		0% {
			transform: scale(1);
		}
		50% {
			transform: scale(1.1);
		}
		100% {
			transform: scale(1);
		}
	}

	.panel {
		margin-top: 10px;
		display: flex;
		justify-content: center;
	}

	.stopVideo {
		margin-top: 10px;
	}

	.stopVideo button {
		background-color: #f44336;
		color: white;
		border: none;
		border-radius: 5px;
		cursor: pointer;
		transition: background-color 0.3s, box-shadow 0.3s;
		margin: 5px;
		/* 居中 */
		display: flex;
		justify-content: center;
	}

	.camerapanel button {
		margin: 10px;
	}
</style>
